package com.fy.fyspace.common.utils;

import cn.hutool.core.util.HexUtil;
import com.fy.fyspace.constant.ResultMessageConstant;
import com.fy.fyspace.ex.ConditionException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 文件哈希工具类
 * 用于计算文件唯一标识，实现秒传功能
 */
@Slf4j
public class FileHashUtil {

  // 缓冲区大小（10MB）
  private static final int BUFFER_SIZE = 10 * 1024 * 1024;

  /**
   * 计算文件的唯一标识
   * 使用文件大小 + SHA-256哈希值组合，支持大文件的分块计算
   *
   * @param file 上传的文件
   * @return 文件唯一标识（格式：fileSize_hash）
   * @throws ConditionException 当文件为空或处理过程中发生错误时
   */
  public static String calculateFileIdentifier(MultipartFile file) {
    // 参数校验
    if (file == null || file.isEmpty()) {
      throw new ConditionException(ResultMessageConstant.PARAMS_ERROR);
    }

    try {
      // 获取文件大小
      long fileSize = file.getSize();

      // 初始化SHA-256算法
      MessageDigest digest = MessageDigest.getInstance("SHA-256");

      // 分块读取文件并计算哈希值
      try (InputStream inputStream = file.getInputStream()) {
        byte[] buffer = new byte[BUFFER_SIZE];
        int bytesRead;

        while ((bytesRead = inputStream.read(buffer)) != -1) {
          digest.update(buffer, 0, bytesRead);
        }

        // 计算最终的哈希值并转换为十六进制字符串
        String sha256Hash = HexUtil.encodeHexStr(digest.digest());

        // 返回组合的唯一标识
        return fileSize + "_" + sha256Hash;
      }

    } catch (NoSuchAlgorithmException e) {
      log.error("SHA-256算法不可用", e);
      throw new ConditionException(ResultMessageConstant.SYSTEM_ERROR + "：哈希算法不可用");
    } catch (IOException e) {
      log.error("读取文件失败", e);
      throw new ConditionException(ResultMessageConstant.SYSTEM_ERROR + "：文件读取失败：" + e.getMessage());
    } catch (Exception e) {
      log.error("计算文件哈希值失败", e);
      throw new ConditionException(ResultMessageConstant.SYSTEM_ERROR + "：" + e.getMessage());
    }
  }
}